import {Inject, Injectable} from '@angular/core';
import {Observable, Subject, timer} from 'rxjs';
import {MessageRegister} from './message-register';
import {MESSAGE} from './message-register.module';
import {deepCopy} from '../../src/functions/copy';
import {filter} from 'rxjs/internal/operators';

/**
 * 消息服务，用于组件之间的通信
 * */
@Injectable()
export class MessageService {
  //
  private subject = new Subject();
  private messageRegister: MessageRegister[];

  constructor(@Inject(MESSAGE) messageRegister) {
    if (messageRegister.length > 0) {
      this.messageRegister = messageRegister[0];
    }
  }

  private getRegister(name: string): MessageRegister {
    let res = null;
    this.messageRegister.forEach((item) => {
      if (item.name === name) {
        res = item;
      }
    });

    if (!res) {
      throw new Error(`${name} 不存在！`);
    }
    return res;
  }

  sendMessage(registerName: string, instance, data?: any) {
    const register = this.getRegister(registerName);
    if (!this.isFromRegistered(register, instance)) {
      throw new Error(`${instance} 没有在MessageRegister.from中注册！`);
    }
    const messageData = deepCopy(register);
    messageData.data = data;
    this.send(messageData);
  }

  // noinspection JSMethodCanBeStatic
  private isFromRegistered(register: MessageRegister, instance: any): boolean {
    let res = false;
    if (typeof register.from === 'object') {
      register.from.forEach((item) => {
        res = res || instance instanceof item;
      });
    } else if (register.from === 'ALL') {
      res = true;
    }

    return res;
  }

  private isToRegistered(register: MessageRegister, instance: any): boolean {
    let res = false;
    register.to.forEach((item) => {
      res = res || instance instanceof item;
    });
    return res;
  }

  private send(data: any) {
    timer(0).subscribe(() => {
      this.subject.next(data);
    });
  }

  getMessage(registerName: string, instance: any): Observable<any> {
    const register = this.getRegister(registerName);

    if (!this.isToRegistered(register, instance)) {
      throw new Error(`${instance} 没有在MessageRegister.to中注册！`);
    }

    return this.subject.asObservable().pipe(
      filter((value) => value['name'] === registerName)
    );
  }
}
